home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / libg_261.zip / libg_261 / libg++ / src / String.cc < prev    next >
C/C++ Source or Header  |  1994-10-12  |  28KB  |  1,301 lines

  1. /* 
  2. Copyright (C) 1988 Free Software Foundation
  3.     written by Doug Lea (dl@rocky.oswego.edu)
  4.  
  5. This file is part of the GNU C++ Library.  This library is free
  6. software; you can redistribute it and/or modify it under the terms of
  7. the GNU Library General Public License as published by the Free
  8. Software Foundation; either version 2 of the License, or (at your
  9. option) any later version.  This library is distributed in the hope
  10. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  11. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  12. PURPOSE.  See the GNU Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17.  
  18. /* 
  19.   String class implementation
  20.  */
  21.  
  22. #ifdef __GNUG__
  23. #pragma implementation
  24. #endif
  25. #include <String.h>
  26. #include <std.h>
  27. #include <ctype.h>
  28. #include <limits.h>
  29. #include <new.h>
  30. #include <builtin.h>
  31.  
  32. void String::error(const char* msg) const
  33. {
  34.   (*lib_error_handler)("String", msg);
  35. }
  36.  
  37. String::operator const char*() const
  38.   return (const char*)chars();
  39. }
  40.  
  41. //  globals
  42.  
  43. StrRep  _nilStrRep = { 0, 1, { 0 } }; // nil strings point here
  44. String _nilString;               // nil SubStrings point here
  45.  
  46.  
  47.  
  48.  
  49. /*
  50.  the following inline fcts are specially designed to work
  51.  in support of String classes, and are not meant as generic replacements
  52.  for libc "str" functions.
  53.  
  54.  inline copy fcts -  I like left-to-right from->to arguments.
  55.  all versions assume that `to' argument is non-null
  56.  
  57.  These are worth doing inline, rather than through calls because,
  58.  via procedural integration, adjacent copy calls can be smushed
  59.  together by the optimizer.
  60. */
  61.  
  62. // copy n bytes
  63. inline static void ncopy(const char* from, char* to, int n)
  64. {
  65.   if (from != to) while (--n >= 0) *to++ = *from++;
  66. }
  67.  
  68. // copy n bytes, null-terminate
  69. inline static void ncopy0(const char* from, char* to, int n)
  70. {
  71.   if (from != to) 
  72.   {
  73.     while (--n >= 0) *to++ = *from++;
  74.     *to = 0;
  75.   }
  76.   else
  77.     to[n] = 0;
  78. }
  79.  
  80. // copy until null
  81. inline static void scopy(const char* from, char* to)
  82. {
  83.   if (from != 0) while((*to++ = *from++) != 0);
  84. }
  85.  
  86. // copy right-to-left
  87. inline static void revcopy(const char* from, char* to, short n)
  88. {
  89.   if (from != 0) while (--n >= 0) *to-- = *from--;
  90. }
  91.  
  92.  
  93. inline static int slen(const char* t) // inline  strlen
  94. {
  95.   if (t == 0)
  96.     return 0;
  97.   else
  98.   {
  99.     const char* a = t;
  100.     while (*a++ != 0);
  101.     return a - 1 - t;
  102.   }
  103. }
  104.  
  105. // minimum & maximum representable rep size
  106.  
  107. #define MAXStrRep_SIZE   ((1 << (sizeof(short) * CHAR_BIT - 1)) - 1)
  108. #define MINStrRep_SIZE   16
  109.  
  110. #ifndef MALLOC_MIN_OVERHEAD
  111. #define MALLOC_MIN_OVERHEAD  4
  112. #endif
  113.  
  114. // The basic allocation primitive:
  115. // Always round request to something close to a power of two.
  116. // This ensures a bit of padding, which often means that
  117. // concatenations don't have to realloc. Plus it tends to
  118. // be faster when lots of Strings are created and discarded,
  119. // since just about any version of malloc (op new()) will
  120. // be faster when it can reuse identically-sized chunks
  121.  
  122. inline static StrRep* Snew(int newsiz)
  123. {
  124.   unsigned int siz = sizeof(StrRep) + newsiz + MALLOC_MIN_OVERHEAD;
  125.   unsigned int allocsiz = MINStrRep_SIZE;
  126.   while (allocsiz < siz) allocsiz <<= 1;
  127.   allocsiz -= MALLOC_MIN_OVERHEAD;
  128.   if (allocsiz >= MAXStrRep_SIZE)
  129.     (*lib_error_handler)("String", "Requested length out of range");
  130.     
  131.   StrRep* rep = (StrRep *) new char[allocsiz];
  132.   rep->sz = allocsiz - sizeof(StrRep);
  133.   return rep;
  134. }
  135.  
  136. // Do-something-while-allocating routines.
  137.  
  138. // We live with two ways to signify empty Sreps: either the
  139. // null pointer (0) or a pointer to the nilStrRep.
  140.  
  141. // We always signify unknown source lengths (usually when fed a char*)
  142. // via len == -1, in which case it is computed.
  143.  
  144. // allocate, copying src if nonull
  145.  
  146. StrRep* Salloc(StrRep* old, const char* src, int srclen, int newlen)
  147. {
  148.   if (old == &_nilStrRep) old = 0;
  149.   if (srclen < 0) srclen = slen(src);
  150.   if (newlen < srclen) newlen = srclen;
  151.   StrRep* rep;
  152.   if (old == 0 || newlen > old->sz)
  153.     rep = Snew(newlen);
  154.   else
  155.     rep = old;
  156.  
  157.   rep->len = newlen;
  158.   ncopy0(src, rep->s, srclen);
  159.  
  160.   if (old != rep && old != 0) delete old;
  161.  
  162.   return rep;
  163. }
  164.  
  165. // reallocate: Given the initial allocation scheme, it will
  166. // generally be faster in the long run to get new space & copy
  167. // than to call realloc
  168.  
  169. static StrRep*
  170. Sresize(StrRep* old, int newlen)
  171. {
  172.   if (old == &_nilStrRep) old = 0;
  173.   StrRep* rep;
  174.   if (old == 0)
  175.     rep = Snew(newlen);
  176.   else if (newlen > old->sz)
  177.   {
  178.     rep = Snew(newlen);
  179.     ncopy0(old->s, rep->s, old->len);
  180.     delete old;
  181.   }
  182.   else
  183.     rep = old;
  184.  
  185.   rep->len = newlen;
  186.  
  187.   return rep;
  188. }
  189.  
  190. void
  191. String::alloc (int newsize)
  192. {
  193.   unsigned short old_len = rep->len;
  194.   rep = Sresize(rep, newsize);
  195.   rep->len = old_len;
  196. }
  197.  
  198. // like allocate, but we know that src is a StrRep
  199.  
  200. StrRep* Scopy(StrRep* old, const StrRep* s)
  201. {
  202.   if (old == &_nilStrRep) old = 0;
  203.   if (s == &_nilStrRep) s = 0;
  204.   if (old == s) 
  205.     return (old == 0)? &_nilStrRep : old;
  206.   else if (s == 0)
  207.   {
  208.     old->s[0] = 0;
  209.     old->len = 0;
  210.     return old;
  211.   }
  212.   else 
  213.   {
  214.     StrRep* rep;
  215.     int newlen = s->len;
  216.     if (old == 0 || newlen > old->sz)
  217.     {
  218.       if (old != 0) delete old;
  219.       rep = Snew(newlen);
  220.     }
  221.     else
  222.       rep = old;
  223.     rep->len = newlen;
  224.     ncopy0(s->s, rep->s, newlen);
  225.     return rep;
  226.   }
  227. }
  228.  
  229. // allocate & concatenate
  230.  
  231. StrRep* Scat(StrRep* old, const char* s, int srclen, const char* t, int tlen)
  232. {
  233.   if (old == &_nilStrRep) old = 0;
  234.   if (srclen < 0) srclen = slen(s);
  235.   if (tlen < 0) tlen = slen(t);
  236.   int newlen = srclen + tlen;
  237.   StrRep* rep;
  238.  
  239.   if (old == 0 || newlen > old->sz || 
  240.       (t >= old->s && t < &(old->s[old->len]))) // beware of aliasing
  241.     rep = Snew(newlen);
  242.   else
  243.     rep = old;
  244.  
  245.   rep->len = newlen;
  246.  
  247.   ncopy(s, rep->s, srclen);
  248.   ncopy0(t, &(rep->s[srclen]), tlen);
  249.  
  250.   if (old != rep && old != 0) delete old;
  251.  
  252.   return rep;
  253. }
  254.  
  255. // double-concatenate
  256.  
  257. StrRep* Scat(StrRep* old, const char* s, int srclen, const char* t, int tlen,
  258.              const char* u, int ulen)
  259. {
  260.   if (old == &_nilStrRep) old = 0;
  261.   if (srclen < 0) srclen = slen(s);
  262.   if (tlen < 0) tlen = slen(t);
  263.   if (ulen < 0) ulen = slen(u);
  264.   int newlen = srclen + tlen + ulen;
  265.   StrRep* rep;
  266.   if (old == 0 || newlen > old->sz || 
  267.       (t >= old->s && t < &(old->s[old->len])) ||
  268.       (u >= old->s && u < &(old->s[old->len])))
  269.     rep = Snew(newlen);
  270.   else
  271.     rep = old;
  272.  
  273.   rep->len = newlen;
  274.  
  275.   ncopy(s, rep->s, srclen);
  276.   ncopy(t, &(rep->s[srclen]), tlen);
  277.   ncopy0(u, &(rep->s[srclen+tlen]), ulen);
  278.  
  279.   if (old != rep && old != 0) delete old;
  280.  
  281.   return rep;
  282. }
  283.  
  284. // like cat, but we know that new stuff goes in the front of existing rep
  285.  
  286. StrRep* Sprepend(StrRep* old, const char* t, int tlen)
  287. {
  288.   char* s;
  289.   int srclen;
  290.   if (old == &_nilStrRep || old == 0)
  291.   {
  292.     s = 0; old = 0; srclen = 0;
  293.   }
  294.   else
  295.   {
  296.     s = old->s; srclen = old->len;
  297.   }
  298.   if (tlen < 0) tlen = slen(t);
  299.   int newlen = srclen + tlen;
  300.   StrRep* rep;
  301.   if (old == 0 || newlen > old->sz || 
  302.       (t >= old->s && t < &(old->s[old->len])))
  303.     rep = Snew(newlen);
  304.   else
  305.     rep = old;
  306.  
  307.   rep->len = newlen;
  308.  
  309.   revcopy(&(s[srclen]), &(rep->s[newlen]), srclen+1);
  310.   ncopy(t, rep->s, tlen);
  311.  
  312.   if (old != rep && old != 0) delete old;
  313.  
  314.   return rep;
  315. }
  316.  
  317.  
  318. // string compare: first argument is known to be non-null
  319.  
  320. inline static int scmp(const char* a, const char* b)
  321. {
  322.   if (b == 0)
  323.     return *a != 0;
  324.   else
  325.   {
  326.     signed char diff = 0;
  327.     while ((diff = *a - *b++) == 0 && *a++ != 0);
  328.     return diff;
  329.   }
  330. }
  331.  
  332.  
  333. inline static int ncmp(const char* a, int al, const char* b, int bl)
  334. {
  335.   int n = (al <= bl)? al : bl;
  336.   signed char diff;
  337.   while (n-- > 0) if ((diff = *a++ - *b++) != 0) return diff;
  338.   return al - bl;
  339. }
  340.  
  341. int fcompare(const String& x, const String& y)
  342. {
  343.   const char* a = x.chars();
  344.   const char* b = y.chars();
  345.   int al = x.length();
  346.   int bl = y.length();
  347.   int n = (al <= bl)? al : bl;
  348.   signed char diff = 0;
  349.   while (n-- > 0)
  350.   {
  351.     char ac = *a++;
  352.     char bc = *b++;
  353.     if ((diff = ac - bc) != 0)
  354.     {
  355.       if (ac >= 'a' && ac <= 'z')
  356.         ac = ac - 'a' + 'A';
  357.       if (bc >= 'a' && bc <= 'z')
  358.         bc = bc - 'a' + 'A';
  359.       if ((diff = ac - bc) != 0)
  360.         return diff;
  361.     }
  362.   }
  363.   return al - bl;
  364. }
  365.  
  366. // these are not inline, but pull in the above inlines, so are 
  367. // pretty fast
  368.  
  369. int compare(const String& x, const char* b)
  370. {
  371.   return scmp(x.chars(), b);
  372. }
  373.  
  374. int compare(const String& x, const String& y)
  375. {
  376.   return scmp(x.chars(), y.chars());
  377. }
  378.  
  379. int compare(const String& x, const SubString& y)
  380. {
  381.   return ncmp(x.chars(), x.length(), y.chars(), y.length());
  382. }
  383.  
  384. int compare(const SubString& x, const String& y)
  385. {
  386.   return ncmp(x.chars(), x.length(), y.chars(), y.length());
  387. }
  388.  
  389. int compare(const SubString& x, const SubString& y)
  390. {
  391.   return ncmp(x.chars(), x.length(), y.chars(), y.length());
  392. }
  393.  
  394. int compare(const SubString& x, const char* b)
  395. {
  396.   if (b == 0)
  397.     return x.length();
  398.   else
  399.   {
  400.     const char* a = x.chars();
  401.     int n = x.length();
  402.     signed char diff;
  403.     while (n-- > 0) if ((diff = *a++ - *b++) != 0) return diff;
  404.     return (*b == 0) ? 0 : -1;
  405.   }
  406. }
  407.  
  408. /*
  409.  index fcts
  410. */
  411.  
  412. int String::search(int start, int sl, char c) const
  413. {
  414.   const char* s = chars();
  415.   if (sl > 0)
  416.   {
  417.     if (start >= 0)
  418.     {
  419.       const char* a = &(s[start]);
  420.       const char* lasta = &(s[sl]);
  421.       while (a < lasta) if (*a++ == c) return --a - s;
  422.     }
  423.     else
  424.     {
  425.       const char* a = &(s[sl + start + 1]);
  426.       while (--a >= s) if (*a == c) return a - s;
  427.     }
  428.   }
  429.   return -1;
  430. }
  431.  
  432. int String::search(int start, int sl, const char* t, int tl) const
  433. {
  434.   const char* s = chars();
  435.   if (tl < 0) tl = slen(t);
  436.   if (sl > 0 && tl > 0)
  437.   {
  438.     if (start >= 0)
  439.     {
  440.       const char* lasts = &(s[sl - tl]);
  441.       const char* lastt = &(t[tl]);
  442.       const char* p = &(s[start]);
  443.  
  444.       while (p <= lasts)
  445.       {
  446.         const char* x = p++;
  447.         const char* y = t;
  448.         while (*x++ == *y++) if (y >= lastt) return --p - s;
  449.       }
  450.     }
  451.     else
  452.     {
  453.       const char* firsts = &(s[tl - 1]);
  454.       const char* lastt =  &(t[tl - 1]);
  455.       const char* p = &(s[sl + start + 1]); 
  456.  
  457.       while (--p >= firsts)
  458.       {
  459.         const char* x = p;
  460.         const char* y = lastt;
  461.         while (*x-- == *y--) if (y < t) return ++x - s;
  462.       }
  463.     }
  464.   }
  465.   return -1;
  466. }
  467.  
  468. int String::match(int start, int sl, int exact, const char* t, int tl) const
  469. {
  470.   if (tl < 0) tl = slen(t);
  471.  
  472.   if (start < 0)
  473.   {
  474.     start = sl + start - tl + 1;
  475.     if (start < 0 || (exact && start != 0))
  476.       return -1;
  477.   }
  478.   else if (exact && sl - start != tl)
  479.     return -1;
  480.  
  481.   if (sl == 0 || tl == 0 || sl - start < tl || start >= sl)
  482.     return -1;
  483.  
  484.   int n = tl;
  485.   const char* s = &(rep->s[start]);
  486.   while (--n >= 0) if (*s++ != *t++) return -1;
  487.   return tl;
  488. }
  489.  
  490. void SubString::assign(const StrRep* ysrc, const char* ys, int ylen)
  491. {
  492.   if (&S == &_nilString) return;
  493.  
  494.   if (ylen < 0) ylen = slen(ys);
  495.   StrRep* targ = S.rep;
  496.   int sl = targ->len - len + ylen;
  497.  
  498.   if (ysrc == targ || sl >= targ->sz)
  499.   {
  500.     StrRep* oldtarg = targ;
  501.     targ = Sresize(0, sl);
  502.     ncopy(oldtarg->s, targ->s, pos);
  503.     ncopy(ys, &(targ->s[pos]), ylen);
  504.     scopy(&(oldtarg->s[pos + len]), &(targ->s[pos + ylen]));
  505.     delete oldtarg;
  506.   }
  507.   else if (len == ylen)
  508.     ncopy(ys, &(targ->s[pos]), len);
  509.   else if (ylen < len)
  510.   {
  511.     ncopy(ys, &(targ->s[pos]), ylen);
  512.     scopy(&(targ->s[pos + len]), &(targ->s[pos + ylen]));
  513.   }
  514.   else
  515.   {
  516.     revcopy(&(targ->s[targ->len]), &(targ->s[sl]), targ->len-pos-len +1);
  517.     ncopy(ys, &(targ->s[pos]), ylen);
  518.   }
  519.   targ->len = sl;
  520.   S.rep = targ;
  521. }
  522.  
  523.  
  524.  
  525. /*
  526.  * substitution
  527.  */
  528.  
  529.  
  530. int String::_gsub(const char* pat, int pl, const char* r, int rl)
  531. {
  532.   int nmatches = 0;
  533.   if (pl < 0) pl = slen(pat);
  534.   if (rl < 0) rl = slen(r);
  535.   int sl = length();
  536.   if (sl <= 0 || pl <= 0 || sl < pl)
  537.     return nmatches;
  538.   
  539.   const char* s = chars();
  540.  
  541.   // prepare to make new rep
  542.   StrRep* nrep = 0;
  543.   int nsz = 0;
  544.   char* x = 0;
  545.  
  546.   int si = 0;
  547.   int xi = 0;
  548.   int remaining = sl;
  549.  
  550.   while (remaining >= pl)
  551.   {
  552.     int pos = search(si, sl, pat, pl);
  553.     if (pos < 0)
  554.       break;
  555.     else
  556.     {
  557.       ++nmatches;
  558.       int mustfit = xi + remaining + rl - pl;
  559.       if (mustfit >= nsz)
  560.       {
  561.         if (nrep != 0) nrep->len = xi;
  562.         nrep = Sresize(nrep, mustfit);
  563.         nsz = nrep->sz;
  564.         x = nrep->s;
  565.       }
  566.       pos -= si;
  567.       ncopy(&(s[si]), &(x[xi]), pos);
  568.       ncopy(r, &(x[xi + pos]), rl);
  569.       si += pos + pl;
  570.       remaining -= pos + pl;
  571.       xi += pos + rl;
  572.     }
  573.   }
  574.  
  575.   if (nrep == 0)
  576.   {
  577.     if (nmatches == 0)
  578.       return nmatches;
  579.     else
  580.       nrep = Sresize(nrep, xi+remaining);
  581.   }
  582.  
  583.   ncopy0(&(s[si]), &(x[xi]), remaining);
  584.   nrep->len = xi + remaining;
  585.  
  586.   if (nrep->len <= rep->sz)   // fit back in if possible
  587.   {
  588.     rep->len = nrep->len;
  589.     ncopy0(nrep->s, rep->s, rep->len);
  590.     delete(nrep);
  591.   }
  592.   else
  593.   {
  594.     delete(rep);
  595.     rep = nrep;
  596.   }
  597.   return nmatches;
  598. }
  599.  
  600. int String::_gsub(const Regex& pat, const char* r, int rl)
  601. {
  602.   int nmatches = 0;
  603.   int sl = length();
  604.   if (sl <= 0)
  605.     return nmatches;
  606.  
  607.   if (rl < 0) rl = slen(r);
  608.  
  609.   const char* s = chars();
  610.  
  611.   StrRep* nrep = 0;
  612.   int nsz = 0;
  613.  
  614.   char* x = 0;
  615.  
  616.   int si = 0;
  617.   int xi = 0;
  618.   int remaining = sl;
  619.   int  pos, pl = 0;                  // how long is a regular expression?
  620.  
  621.   while (remaining > 0)
  622.   {
  623.     pos = pat.search(s, sl, pl, si); // unlike string search, the pos returned here is absolute
  624.     if (pos < 0 || pl <= 0)
  625.       break;
  626.     else
  627.     {
  628.       ++nmatches;
  629.       int mustfit = xi + remaining + rl - pl;
  630.       if (mustfit >= nsz)
  631.       {
  632.         if (nrep != 0) nrep->len = xi;
  633.         nrep = Sresize(nrep, mustfit);
  634.         x = nrep->s;
  635.         nsz = nrep->sz;
  636.       }
  637.       pos -= si;
  638.       ncopy(&(s[si]), &(x[xi]), pos);
  639.       ncopy(r, &(x[xi + pos]), rl);
  640.       si += pos + pl;
  641.       remaining -= pos + pl;
  642.       xi += pos + rl;
  643.     }
  644.   }
  645.  
  646.   if (nrep == 0)
  647.   {
  648.     if (nmatches == 0)
  649.       return nmatches;
  650.     else
  651.       nrep = Sresize(nrep, xi+remaining);
  652.   }
  653.  
  654.   ncopy0(&(s[si]), &(x[xi]), remaining);
  655.   nrep->len = xi + remaining;
  656.  
  657.   if (nrep->len <= rep->sz)   // fit back in if possible
  658.   {
  659.     rep->len = nrep->len;
  660.     ncopy0(nrep->s, rep->s, rep->len);
  661.     delete(nrep);
  662.   }
  663.   else
  664.   {
  665.     delete(rep);
  666.     rep = nrep;
  667.   }
  668.   return nmatches;
  669. }
  670.  
  671.  
  672. /*
  673.  * deletion
  674.  */
  675.  
  676. void String::del(int pos, int len)
  677. {
  678.   if (pos < 0 || len <= 0 || (unsigned)(pos + len) > length()) return;
  679.   int nlen = length() - len;
  680.   int first = pos + len;
  681.   ncopy0(&(rep->s[first]), &(rep->s[pos]), length() - first);
  682.   rep->len = nlen;
  683. }
  684.  
  685. void String::del(const Regex& r, int startpos)
  686. {
  687.   int mlen;
  688.   int first = r.search(chars(), length(), mlen, startpos);
  689.   del(first, mlen);
  690. }
  691.  
  692. void String::del(const char* t, int startpos)
  693. {
  694.   int tlen = slen(t);
  695.   int p = search(startpos, length(), t, tlen);
  696.   del(p, tlen);
  697. }
  698.  
  699. void String::del(const String& y, int startpos)
  700. {
  701.   del(search(startpos, length(), y.chars(), y.length()), y.length());
  702. }
  703.  
  704. void String::del(const SubString& y, int startpos)
  705. {
  706.   del(search(startpos, length(), y.chars(), y.length()), y.length());
  707. }
  708.  
  709. void String::del(char c, int startpos)
  710. {
  711.   del(search(startpos, length(), c), 1);
  712. }
  713.  
  714. /*
  715.  * substring extraction
  716.  */
  717.  
  718.  
  719. SubString String::at(int first, int len)
  720. {
  721.   return _substr(first, len);
  722. }
  723.  
  724. SubString String::operator() (int first, int len)
  725. {
  726.   return _substr(first, len);
  727. }
  728.  
  729. SubString String::before(int pos)
  730. {
  731.   return _substr(0, pos);
  732. }
  733.  
  734. SubString String::through(int pos)
  735. {
  736.   return _substr(0, pos+1);
  737. }
  738.  
  739. SubString String::after(int pos)
  740. {
  741.   return _substr(pos + 1, length() - (pos + 1));
  742. }
  743.  
  744. SubString String::from(int pos)
  745. {
  746.   return _substr(pos, length() - pos);
  747. }
  748.  
  749. SubString String::at(const String& y, int startpos)
  750. {
  751.   int first = search(startpos, length(), y.chars(), y.length());
  752.   return _substr(first,  y.length());
  753. }
  754.  
  755. SubString String::at(const SubString& y, int startpos)
  756. {
  757.   int first = search(startpos, length(), y.chars(), y.length());
  758.   return _substr(first, y.length());
  759. }
  760.  
  761. SubString String::at(const Regex& r, int startpos)
  762. {
  763.   int mlen;
  764.   int first = r.search(chars(), length(), mlen, startpos);
  765.   return _substr(first, mlen);
  766. }
  767.  
  768. SubString String::at(const char* t, int startpos)
  769. {
  770.   int tlen = slen(t);
  771.   int first = search(startpos, length(), t, tlen);
  772.   return _substr(first, tlen);
  773. }
  774.  
  775. SubString String::at(char c, int startpos)
  776. {
  777.   int first = search(startpos, length(), c);
  778.   return _substr(first, 1);
  779. }
  780.  
  781. SubString String::before(const String& y, int startpos)
  782. {
  783.   int last = search(startpos, length(), y.chars(), y.length());
  784.   return _substr(0, last);
  785. }
  786.  
  787. SubString String::before(const SubString& y, int startpos)
  788. {
  789.   int last = search(startpos, length(), y.chars(), y.length());
  790.   return _substr(0, last);
  791. }
  792.  
  793. SubString String::before(const Regex& r, int startpos)
  794. {
  795.   int mlen;
  796.   int first = r.search(chars(), length(), mlen, startpos);
  797.   return _substr(0, first);
  798. }
  799.  
  800. SubString String::before(char c, int startpos)
  801. {
  802.   int last = search(startpos, length(), c);
  803.   return _substr(0, last);
  804. }
  805.  
  806. SubString String::before(const char* t, int startpos)
  807. {
  808.   int tlen = slen(t);
  809.   int last = search(startpos, length(), t, tlen);
  810.   return _substr(0, last);
  811. }
  812.  
  813. SubString String::through(const String& y, int startpos)
  814. {
  815.   int last = search(startpos, length(), y.chars(), y.length());
  816.   if (last >= 0) last += y.length();
  817.   return _substr(0, last);
  818. }
  819.  
  820. SubString String::through(const SubString& y, int startpos)
  821. {
  822.   int last = search(startpos, length(), y.chars(), y.length());
  823.   if (last >= 0) last += y.length();
  824.   return _substr(0, last);
  825. }
  826.  
  827. SubString String::through(const Regex& r, int startpos)
  828. {
  829.   int mlen;
  830.   int first = r.search(chars(), length(), mlen, startpos);
  831.   if (first >= 0) first += mlen;
  832.   return _substr(0, first);
  833. }
  834.  
  835. SubString String::through(char c, int startpos)
  836. {
  837.   int last = search(startpos, length(), c);
  838.   if (last >= 0) last += 1;
  839.   return _substr(0, last);
  840. }
  841.  
  842. SubString String::through(const char* t, int startpos)
  843. {
  844.   int tlen = slen(t);
  845.   int last = search(startpos, length(), t, tlen);
  846.   if (last >= 0) last += tlen;
  847.   return _substr(0, last);
  848. }
  849.  
  850. SubString String::after(const String& y, int startpos)
  851. {
  852.   int first = search(startpos, length(), y.chars(), y.length());
  853.   if (first >= 0) first += y.length();
  854.   return _substr(first, length() - first);
  855. }
  856.  
  857. SubString String::after(const SubString& y, int startpos)
  858. {
  859.   int first = search(startpos, length(), y.chars(), y.length());
  860.   if (first >= 0) first += y.length();
  861.   return _substr(first, length() - first);
  862. }
  863.  
  864. SubString String::after(char c, int startpos)
  865. {
  866.   int first = search(startpos, length(), c);
  867.   if (first >= 0) first += 1;
  868.   return _substr(first, length() - first);
  869. }
  870.  
  871. SubString String::after(const Regex& r, int startpos)
  872. {
  873.   int mlen;
  874.   int first = r.search(chars(), length(), mlen, startpos);
  875.   if (first >= 0) first += mlen;
  876.   return _substr(first, length() - first);
  877. }
  878.  
  879. SubString String::after(const char* t, int startpos)
  880. {
  881.   int tlen = slen(t);
  882.   int first = search(startpos, length(), t, tlen);
  883.   if (first >= 0) first += tlen;
  884.   return _substr(first, length() - first);
  885. }
  886.  
  887. SubString String::from(const String& y, int startpos)
  888. {
  889.   int first = search(startpos, length(), y.chars(), y.length());
  890.   return _substr(first, length() - first);
  891. }
  892.  
  893. SubString String::from(const SubString& y, int startpos)
  894. {
  895.   int first = search(startpos, length(), y.chars(), y.length());
  896.   return _substr(first, length() - first);
  897. }
  898.  
  899. SubString String::from(const Regex& r, int startpos)
  900. {
  901.   int mlen;
  902.   int first = r.search(chars(), length(), mlen, startpos);
  903.   return _substr(first, length() - first);
  904. }
  905.  
  906. SubString String::from(char c, int startpos)
  907. {
  908.   int first = search(startpos, length(), c);
  909.   return _substr(first, length() - first);
  910. }
  911.  
  912. SubString String::from(const char* t, int startpos)
  913. {
  914.   int tlen = slen(t);
  915.   int first = search(startpos, length(), t, tlen);
  916.   return _substr(first, length() - first);
  917. }
  918.  
  919.  
  920.  
  921. /*
  922.  * split/join
  923.  */
  924.  
  925.  
  926. int split(const String& src, String results[], int n, const String& sep)
  927. {
  928.   String x = src;
  929.   const char* s = x.chars();
  930.   int sl = x.length();
  931.   int i = 0;
  932.   int pos = 0;
  933.   while (i < n && pos < sl)
  934.   {
  935.     int p = x.search(pos, sl, sep.chars(), sep.length());
  936.     if (p < 0)
  937.       p = sl;
  938.     results[i].rep = Salloc(results[i].rep, &(s[pos]), p - pos, p - pos);
  939.     i++;
  940.     pos = p + sep.length();
  941.   }
  942.   return i;
  943. }
  944.  
  945. int split(const String& src, String results[], int n, const Regex& r)
  946. {
  947.   String x = src;
  948.   const char* s = x.chars();
  949.   int sl = x.length();
  950.   int i = 0;
  951.   int pos = 0;
  952.   int p, matchlen;
  953.   while (i < n && pos < sl)
  954.   {
  955.     p = r.search(s, sl, matchlen, pos);
  956.     if (p < 0)
  957.       p = sl;
  958.     results[i].rep = Salloc(results[i].rep, &(s[pos]), p - pos, p - pos);
  959.     i++;
  960.     pos = p + matchlen;
  961.   }
  962.   return i;
  963. }
  964.  
  965.  
  966. #if defined(__GNUG__) && !defined(_G_NO_NRV)
  967. #define RETURN(r) return
  968. #define RETURNS(r) return r;
  969. #define RETURN_OBJECT(TYPE, NAME) /* nothing */
  970. #else /* _G_NO_NRV */
  971. #define RETURN(r) return r
  972. #define RETURNS(r) /* nothing */
  973. #define RETURN_OBJECT(TYPE, NAME) TYPE NAME;
  974. #endif
  975.  
  976. String join(String src[], int n, const String& separator) RETURNS(x)
  977. {
  978.   RETURN_OBJECT(String,x)
  979.   String sep = separator;
  980.   int xlen = 0;
  981.   for (int i = 0; i < n; ++i)
  982.     xlen += src[i].length();
  983.   xlen += (n - 1) * sep.length();
  984.  
  985.   x.rep = Sresize (x.rep, xlen);
  986.  
  987.   int j = 0;
  988.   
  989.   for (i = 0; i < n - 1; ++i)
  990.   {
  991.     ncopy(src[i].chars(), &(x.rep->s[j]), src[i].length());
  992.     j += src[i].length();
  993.     ncopy(sep.chars(), &(x.rep->s[j]), sep.length());
  994.     j += sep.length();
  995.   }
  996.   ncopy0(src[i].chars(), &(x.rep->s[j]), src[i].length());
  997.   RETURN(x);
  998. }
  999.   
  1000. /*
  1001.  misc
  1002. */
  1003.  
  1004.     
  1005. StrRep* Sreverse(const StrRep* src, StrRep* dest)
  1006. {
  1007.   int n = src->len;
  1008.   if (src != dest)
  1009.     dest = Salloc(dest, src->s, n, n);
  1010.   if (n > 0)
  1011.   {
  1012.     char* a = dest->s;
  1013.     char* b = &(a[n - 1]);
  1014.     while (a < b)
  1015.     {
  1016.       char t = *a;
  1017.       *a++ = *b;
  1018.       *b-- = t;
  1019.     }
  1020.   }
  1021.   return dest;
  1022. }
  1023.  
  1024.  
  1025. StrRep* Supcase(const StrRep* src, StrRep* dest)
  1026. {
  1027.   int n = src->len;
  1028.   if (src != dest) dest = Salloc(dest, src->s, n, n);
  1029.   char* p = dest->s;
  1030.   char* e = &(p[n]);
  1031.   for (; p < e; ++p) if (islower(*p)) *p = toupper(*p);
  1032.   return dest;
  1033. }
  1034.  
  1035. StrRep* Sdowncase(const StrRep* src, StrRep* dest)
  1036. {
  1037.   int n = src->len;
  1038.   if (src != dest) dest = Salloc(dest, src->s, n, n);
  1039.   char* p = dest->s;
  1040.   char* e = &(p[n]);
  1041.   for (; p < e; ++p) if (isupper(*p)) *p = tolower(*p);
  1042.   return dest;
  1043. }
  1044.  
  1045. StrRep* Scapitalize(const StrRep* src, StrRep* dest)
  1046. {
  1047.   int n = src->len;
  1048.   if (src != dest) dest = Salloc(dest, src->s, n, n);
  1049.  
  1050.   char* p = dest->s;
  1051.   char* e = &(p[n]);
  1052.   for (; p < e; ++p)
  1053.   {
  1054.     int at_word;
  1055.     if (at_word = islower(*p))
  1056.       *p = toupper(*p);
  1057.     else 
  1058.       at_word = isupper(*p) || isdigit(*p);
  1059.  
  1060.     if (at_word)
  1061.     {
  1062.       while (++p < e)
  1063.       {
  1064.         if (isupper(*p))
  1065.           *p = tolower(*p);
  1066.     /* A '\'' does not break a word, so that "Nathan's" stays
  1067.        "Nathan's" rather than turning into "Nathan'S". */
  1068.         else if (!islower(*p) && !isdigit(*p) && (*p != '\''))
  1069.           break;
  1070.       }
  1071.     }
  1072.   }
  1073.   return dest;
  1074. }
  1075.  
  1076. #if defined(__GNUG__) && !defined(_G_NO_NRV)
  1077.  
  1078. String replicate(char c, int n) return w;
  1079. {
  1080.   w.rep = Sresize(w.rep, n);
  1081.   char* p = w.rep->s;
  1082.   while (n-- > 0) *p++ = c;
  1083.   *p = 0;
  1084. }
  1085.  
  1086. String replicate(const String& y, int n) return w
  1087. {
  1088.   int len = y.length();
  1089.   w.rep = Sresize(w.rep, n * len);
  1090.   char* p = w.rep->s;
  1091.   while (n-- > 0)
  1092.   {
  1093.     ncopy(y.chars(), p, len);
  1094.     p += len;
  1095.   }
  1096.   *p = 0;
  1097. }
  1098.  
  1099. String common_prefix(const String& x, const String& y, int startpos) return r;
  1100. {
  1101.   const char* xchars = x.chars();
  1102.   const char* ychars = y.chars();
  1103.   const char* xs = &(xchars[startpos]);
  1104.   const char* ss = xs;
  1105.   const char* topx = &(xchars[x.length()]);
  1106.   const char* ys = &(ychars[startpos]);
  1107.   const char* topy = &(ychars[y.length()]);
  1108.   for (int l = 0; xs < topx && ys < topy && *xs++ == *ys++; ++l);
  1109.   r.rep = Salloc(r.rep, ss, l, l);
  1110. }
  1111.  
  1112. String common_suffix(const String& x, const String& y, int startpos) return r;
  1113. {
  1114.   const char* xchars = x.chars();
  1115.   const char* ychars = y.chars();
  1116.   const char* xs = &(xchars[x.length() + startpos]);
  1117.   const char* botx = xchars;
  1118.   const char* ys = &(ychars[y.length() + startpos]);
  1119.   const char* boty = ychars;
  1120.   for (int l = 0; xs >= botx && ys >= boty && *xs == *ys ; --xs, --ys, ++l);
  1121.   r.rep = Salloc(r.rep, ++xs, l, l);
  1122. }
  1123.  
  1124. #else
  1125.  
  1126. String replicate(char c, int n)
  1127. {
  1128.   String w;
  1129.   w.rep = Sresize(w.rep, n);
  1130.   char* p = w.rep->s;
  1131.   while (n-- > 0) *p++ = c;
  1132.   *p = 0;
  1133.   return w;
  1134. }
  1135.  
  1136. String replicate(const String& y, int n)
  1137. {
  1138.   String w;
  1139.   int len = y.length();
  1140.   w.rep = Sresize(w.rep, n * len);
  1141.   char* p = w.rep->s;
  1142.   while (n-- > 0)
  1143.   {
  1144.     ncopy(y.chars(), p, len);
  1145.     p += len;
  1146.   }
  1147.   *p = 0;
  1148.   return w;
  1149. }
  1150.  
  1151. String common_prefix(const String& x, const String& y, int startpos)
  1152. {
  1153.   String r;
  1154.   const char* xchars = x.chars();
  1155.   const char* ychars = y.chars();
  1156.   const char* xs = &(xchars[startpos]);
  1157.   const char* ss = xs;
  1158.   const char* topx = &(xchars[x.length()]);
  1159.   const char* ys = &(ychars[startpos]);
  1160.   const char* topy = &(ychars[y.length()]);
  1161.   for (int l = 0; xs < topx && ys < topy && *xs++ == *ys++; ++l);
  1162.   r.rep = Salloc(r.rep, ss, l, l);
  1163.   return r;
  1164. }
  1165.  
  1166. String common_suffix(const String& x, const String& y, int startpos) 
  1167. {
  1168.   String r;
  1169.   const char* xchars = x.chars();
  1170.   const char* ychars = y.chars();
  1171.   const char* xs = &(xchars[x.length() + startpos]);
  1172.   const char* botx = xchars;
  1173.   const char* ys = &(ychars[y.length() + startpos]);
  1174.   const char* boty = ychars;
  1175.   for (int l = 0; xs >= botx && ys >= boty && *xs == *ys ; --xs, --ys, ++l);
  1176.   r.rep = Salloc(r.rep, ++xs, l, l);
  1177.   return r;
  1178. }
  1179.  
  1180. #endif
  1181.  
  1182. // IO
  1183.  
  1184. istream& operator>>(istream& s, String& x)
  1185. {
  1186.   if (!s.ipfx(0) || (!(s.flags() & ios::skipws) && !ws(s)))
  1187.   {
  1188.     s.clear(ios::failbit|s.rdstate()); // Redundant if using GNU iostreams.
  1189.     return s;
  1190.   }
  1191.   int ch;
  1192.   int i = 0;
  1193.   x.rep = Sresize(x.rep, 20);
  1194.   register streambuf *sb = s.rdbuf();
  1195.   while ((ch = sb->sbumpc()) != EOF)
  1196.   {
  1197.     if (isspace(ch))
  1198.       break;
  1199.     if (i >= x.rep->sz - 1)
  1200.       x.rep = Sresize(x.rep, i+1);
  1201.     x.rep->s[i++] = ch;
  1202.   }
  1203.   x.rep->s[i] = 0;
  1204.   x.rep->len = i;
  1205.   int new_state = s.rdstate();
  1206.   if (i == 0) new_state |= ios::failbit;
  1207.   if (ch == EOF) new_state |= ios::eofbit;
  1208.   s.clear(new_state);
  1209.   return s;
  1210. }
  1211.  
  1212. int readline(istream& s, String& x, char terminator, int discard)
  1213. {
  1214.   if (!s.ipfx(0))
  1215.     return 0;
  1216.   int ch;
  1217.   int i = 0;
  1218.   x.rep = Sresize(x.rep, 80);
  1219.   register streambuf *sb = s.rdbuf();
  1220.   while ((ch = sb->sbumpc()) != EOF)
  1221.   {
  1222.     if (ch != terminator || !discard)
  1223.     {
  1224.       if (i >= x.rep->sz - 1)
  1225.         x.rep = Sresize(x.rep, i+1);
  1226.       x.rep->s[i++] = ch;
  1227.     }
  1228.     if (ch == terminator)
  1229.       break;
  1230.   }
  1231.   x.rep->s[i] = 0;
  1232.   x.rep->len = i;
  1233.   if (ch == EOF) s.clear(ios::eofbit|s.rdstate());
  1234.   return i;
  1235. }
  1236.  
  1237.  
  1238. ostream& operator<<(ostream& s, const SubString& x)
  1239.   const char* a = x.chars();
  1240.   const char* lasta = &(a[x.length()]);
  1241.   while (a < lasta)
  1242.     s.put(*a++);
  1243.   return(s);
  1244. }
  1245.  
  1246. // from John.Willis@FAS.RI.CMU.EDU
  1247.  
  1248. int String::freq(const SubString& y) const
  1249. {
  1250.   int found = 0;
  1251.   for (unsigned int i = 0; i < length(); i++) 
  1252.     if (match(i,length(),0,y.chars(), y.length())>= 0) found++;
  1253.   return(found);
  1254. }
  1255.  
  1256. int String::freq(const String& y) const
  1257. {
  1258.   int found = 0;
  1259.   for (unsigned int i = 0; i < length(); i++) 
  1260.     if (match(i,length(),0,y.chars(),y.length()) >= 0) found++;
  1261.   return(found);
  1262. }
  1263.  
  1264. int String::freq(const char* t) const
  1265. {
  1266.   int found = 0;
  1267.   for (unsigned int i = 0; i < length(); i++) 
  1268.     if (match(i,length(),0,t) >= 0) found++;
  1269.   return(found);
  1270. }
  1271.  
  1272. int String::freq(char c) const
  1273. {
  1274.   int found = 0;
  1275.   for (unsigned int i = 0; i < length(); i++) 
  1276.     if (match(i,length(),0,&c,1) >= 0) found++;
  1277.   return(found);
  1278. }
  1279.  
  1280.  
  1281. int String::OK() const
  1282. {
  1283.   if (rep == 0             // don't have a rep
  1284.     || rep->len > rep->sz     // string oustide bounds
  1285.     || rep->s[rep->len] != 0)   // not null-terminated
  1286.       error("invariant failure");
  1287.   return 1;
  1288. }
  1289.  
  1290. int SubString::OK() const
  1291. {
  1292.   int v = S != (const char*)0; // have a String;
  1293.   v &= S.OK();                 // that is legal
  1294.   v &= pos + len >= S.rep->len;// pos and len within bounds
  1295.   if (!v) S.error("SubString invariant failure");
  1296.   return v;
  1297. }
  1298.  
  1299.